

package org.jetnuke.modules.blog.utils;

import java.net.HttpURLConnection;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.HeadMethod;
import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.XmlRpcHandler;
import org.jetnuke.dao.BlogCommentDAO;
import org.jetnuke.dao.BlogPostDAO;
import org.jetnuke.dao.DataAccessDriver;
import org.jetnuke.entities.BlogComment;
import org.jetnuke.entities.BlogPost;
import org.jetnuke.servlets.utilities.StringUtils;

public class PingBackHandler implements XmlRpcHandler{
	protected static final int PINGBACK_GENERIC_FAULT_CODE = 0;
    protected static final int PINGBACK_SOURCE_URI_NON_EXISTENT_CODE = 16;
    protected static final int PINGBACK_NO_LINK_TO_TARGET_URI_CODE = 17;
    protected static final int PINGBACK_TARGET_URI_NON_EXISTENT_CODE = 32;
    protected static final int PINGBACK_TARGET_URI_NOT_ENABLED_CODE = 33;
    protected static final int PINGBACK_ALREADY_REGISTERED_CODE = 48;
    protected static final int PINGBACK_ACCESS_DENIED_CODE = 49;
    protected static final int PINGBACK_UPSTREAM_SERVER_ERROR_CODE = 50;
    
	private HttpServletRequest request;
	public PingBackHandler(HttpServletRequest request){
		this.request=request;
	}
	public String ping(String sourceURI, String targetURI)throws XmlRpcException{
		HttpClient client = new HttpClient();
		GetMethod gm=new GetMethod(sourceURI);
		client.setConnectionTimeout(8000);
		String sourcePage=null;
		try {
			client.executeMethod(gm);
			sourcePage=gm.getResponseBodyAsString();
		} catch (Throwable e) {
			throw new XmlRpcException(PINGBACK_GENERIC_FAULT_CODE, "Unable to retrieve source URI");
		}
		
		if (sourcePage.indexOf(targetURI) == -1) {

            throw new XmlRpcException(PINGBACK_NO_LINK_TO_TARGET_URI_CODE, "Target URI not found in source URI");
        }
		HeadMethod hm=new HeadMethod(targetURI);
		try{
			int returnValue=client.executeMethod(hm);
			if(returnValue!=HttpURLConnection.HTTP_OK){
				throw new Exception();
			}
		}catch (Throwable t){
			throw new XmlRpcException(PINGBACK_TARGET_URI_NON_EXISTENT_CODE, "Target URI does not exist");
		}
		int targetIndex=targetURI.indexOf("id=");
		String ID=targetURI.substring(targetIndex+3);
		int id=-1;
		BlogPost bp=null;
		try{
			id=Integer.parseInt(ID);
			BlogPostDAO bpm=DataAccessDriver.getInst().newBlogPostDAO();
			bp=bpm.retrieveByPK(id);
			if(bp.getID()!=id){
				throw new Exception();
			}
				
		}catch(Throwable t){
			throw new XmlRpcException(PINGBACK_TARGET_URI_NON_EXISTENT_CODE, "Target URI does not exist");
		}
		if(!"open".equals(bp.getPINGSTATUS())){
			throw new XmlRpcException(PINGBACK_TARGET_URI_NOT_ENABLED_CODE, "Target URI does not support pingbacks");
		}
		BlogCommentDAO bcm=DataAccessDriver.getInst().newBlogCommentDAO();
		List commentByPostList=null;
		try {
			bcm.selectByPostID(id);
			Iterator it=commentByPostList.iterator();
			while(it.hasNext()){
				BlogComment bc=(BlogComment)it.next();
				if("pingback".equals(bc.getTYPE())&& sourceURI.equals(bc.getAUTHOR_URL())){
					throw new XmlRpcException(PINGBACK_ALREADY_REGISTERED_CODE, "The pingback has already been registered.");
				}
			}
		} catch (Exception e) {
			
		}
		
		BlogComment bc=new BlogComment();
		String ua=request.getHeader("user-agent");
		if(ua==null)
			ua="";
		String ip=request.getRemoteAddr();
		if(ip==null)
			ip="";
		bc.setAUTHOR("");
		bc.setAGENT(ua);
		
		bc.setAUTHOR_EMAIL("");
		bc.setAUTHOR_IP(ip);
		bc.setAUTHOR_URL(sourceURI);
		String comment=getExcerptFromSource(sourcePage,targetURI);
		bc.setCONTENT("[...]"+comment+"[...]");
		bc.setDATE(new GregorianCalendar().getTime());
		bc.setPARENT(0);
		bc.setPOST_ID(id);
		bc.setTYPE("pingback");
		int uid=1;
		
		String approved="0";
		//if(uid==bp.getAID())
		approved="1"; //TODO give more flexibility!!
		bc.setAPPROVED(approved);
		bc.setUSER_ID(uid);
		
		try {
			bcm.addNew(bc);
		} catch (Exception e) {
			throw new XmlRpcException(PINGBACK_GENERIC_FAULT_CODE, "Unable to retrieve source URI");
		}
		return "Registered pingback from: " + sourceURI + " to: " + targetURI;
	}
	public String ping(Vector values) throws XmlRpcException{
		if(values.size()<2 || values.get(0)==null || ((String)values.get(0)).trim().length()==0){
			throw new XmlRpcException(PINGBACK_SOURCE_URI_NON_EXISTENT_CODE, "Pingback must include a source URI");
		}
		return ping((String)values.get(0),(String)values.get(1));
		
	}
	protected String getExcerptFromSource(String source, String targetURI) {
        String excerpt = null;

        int startOfTarget = source.indexOf(targetURI);
        if (startOfTarget != -1) {
            int startOfExcerpt = startOfTarget - 200;
            if (startOfExcerpt < 0) {
                startOfExcerpt = 0;
            }

            int endOfExcerpt = startOfTarget + 200;
            if (endOfExcerpt > source.length()) {
                endOfExcerpt = source.length();
            }

            excerpt = source.substring(startOfExcerpt, endOfExcerpt);
            excerpt = StringUtils.filterText(excerpt,true);
        }

        return excerpt;
    }
	public Object execute(String arg0, Vector values) throws Exception {
		return ping(values);
	}
}
